﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TRACv2.Persistence;
using TRACv2.Domain.DTO;
using System.Diagnostics.CodeAnalysis;
using AutoMapper;
using TRACv2.Common.Enumerations;
using System.Collections.Generic;


namespace TRACv2.Persistence.Test
{
    // Author: Ryan Redburn
    // Project: TRACv2
    // Date: 3/21/2014

    [TestClass]
    [ExcludeFromCodeCoverage]
    public class TicketRepositoryTest
    {
        // GetAll

        [TestMethod]
        public void GetAll_ValidFilterValues_ExpectedReturn()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            Mapper.CreateMap<Ticket, TicketDTO>();

            // Act
            var tickets = ticketRepo.GetAll(true, 4, 4, 3, Issue.Hardware, Priority.Urgent, Status.Hold, new DateTime(2012, 1, 14), new DateTime(2014, 4, 23));

            // Assert
            Assert.AreEqual(1, (tickets as List<TicketDTO>).Count);
        }

        [TestMethod]
        public void GetAll_ContactBelowRange_ArgumentOutOfRangeException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            int contact = 0;
            var assert = false;

            // Act
            try
            {
                var tickets = ticketRepo.GetAll(true, contact);
            }
            catch (ArgumentOutOfRangeException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void GetAll_CreatorBelowRange_ArgumentOutOfRangeException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            int creator = 0;
            var assert = false;

            // Act
            try
            {
                var tickets = ticketRepo.GetAll(true, creator: creator);
            }
            catch (ArgumentOutOfRangeException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void GetAll_AssignedBelowRange_ArgumentOutOfRangeException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            int assigned = 0;
            var assert = false;

            // Act
            try
            {
                var tickets = ticketRepo.GetAll(true, assigned: assigned);
            }
            catch (ArgumentOutOfRangeException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void GetAll_IncompleteDateRangeNoStart_ArgumentOutOfRangeException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            DateTime? startDate = null;
            DateTime? endDate = new DateTime(2000, 2, 15);
            var assert = false;

            // Act
            try
            {
                var tickets = ticketRepo.GetAll(true, startDate: startDate, endDate: endDate);
            }
            catch (ArgumentOutOfRangeException)
            {
                assert = true;
            }
            finally
            {
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void GetAll_IncompleteDateRangeNoEnd_ArgumentOutOfRangeException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            DateTime? startDate = new DateTime(2000, 2, 15);
            DateTime? endDate = null;
            var assert = false;

            // Act
            try
            {
                var tickets = ticketRepo.GetAll(true, startDate: startDate, endDate: endDate);
            }
            catch (ArgumentOutOfRangeException)
            {
                assert = true;
            }
            finally
            {
                Assert.IsTrue(assert);
            }
        }

        // GetByNumber

        [TestMethod]
        public void GetByNumber_ValidNumber_ValidReturn()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            Mapper.CreateMap<Ticket, TicketDTO>();
            var number = "2014Mar26hford12:07";

            // Act
            var ticket = ticketRepo.GetByNumber(number);

            // Assert
            Assert.IsNotNull(ticket);
        }

        [TestMethod]
        public void GetByNumber_NullNumberValue_ArgumentNullException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            string number = null;
            var assert = false;

            // Act
            try
            {
                var ticket = ticketRepo.GetByNumber(number);
            }
            catch (ArgumentNullException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void GetByNumber_EmptyNumberValue_ArgumentNullException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            string number = "";
            var assert = false;

            // Act
            try
            {
                var ticket = ticketRepo.GetByNumber(number);
            }
            catch (ArgumentNullException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void GetByNumber_NonexistingNumber_InvalidOperationException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            string number = "1990Apr2jsmith19:07"; // Does not exist in database
            var assert = false;

            // Act
            try
            {
                var ticket = ticketRepo.GetByNumber(number);
            }
            catch (InvalidOperationException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        // Add

        [TestMethod]
        public void Add_ValidTicket_SuccessfulAddition()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            Mapper.CreateMap<TicketDTO, Ticket>();
            var ticket = new TicketDTO
            {
                DateCreated = DateTime.Now,
                Contact = 3,
                Creator = 3,
                Assigned = 3,
                Issue = Issue.Desktop,
                Priority = Priority.Convenient,
                Status = Status.Assigned,
                Note = "test ticket"
            };

            // Act
            ticketRepo.Add(ticket);

            // Assert
            Assert.IsTrue(true);
        }

        [TestMethod]
        public void Add_NullTicketDTO_ArgumentNullException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            TicketDTO ticket = null;
            var assert = false;

            // Act
            try
            {
                ticketRepo.Add(ticket);
            }
            catch (ArgumentNullException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        // Update

        [TestMethod]
        public void Update_ValidTicket_SuccessfulAddition()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            Mapper.CreateMap<TicketDTO, Ticket>();
            var tickets = ticketRepo.GetAll(false) as List<TicketDTO>;
            var ticket = tickets[0];
            var ticketUpdate = new TicketDTO
            {
                Number = ticket.Number,
                DateCreated = DateTime.Now,
                Contact = 3,
                Creator = 3,
                Assigned = 3,
                Issue = Issue.Desktop,
                Priority = Priority.Convenient,
                Status = Status.Assigned,
                Note = "test ticket"
            };

            // Act
            ticketRepo.Update(ticketUpdate);

            // Assert
            Assert.IsTrue(true);
        }

        [TestMethod]
        public void Update_NullTicketDTO_ArgumentNullException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            TicketDTO ticket = null;
            var assert = false;

            // Act
            try
            {
                ticketRepo.Update(ticket);
            }
            catch (ArgumentNullException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void Update_NonexistingTicket_InvalidOperationException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            var ticket = new TicketDTO();
            var assert = false;

            // Act
            try
            {
                ticket.Number = "1990Apr2jsmith19:07"; // Does not exist in database
                ticketRepo.Update(ticket);
            }
            catch (InvalidOperationException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        // Delete

        [TestMethod]
        public void Delete_ValidTicket_SuccessfulRemoval()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            Mapper.CreateMap<TicketDTO, Ticket>();
            var ticket = (ticketRepo.GetAll(false) as List<TicketDTO>)[0];

            // Act
            ticketRepo.Delete(ticket);

            // Assert
            Assert.IsTrue(true);
        }

        [TestMethod]
        public void Delete_NullTicketDTO_ArgumentNullException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            TicketDTO ticket = null;
            var assert = false;

            // Act
            try
            {
                ticketRepo.Delete(ticket);
            }
            catch (ArgumentNullException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void Delete_NonexistingTicket_InvalidOperationException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            var ticket = new TicketDTO();
            var assert = false;

            // Act
            try
            {
                ticket.Number = "1990Apr2jsmith19:07"; // Does not exist in database
                ticketRepo.Delete(ticket);
            }
            catch (InvalidOperationException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        // Archive

        [TestMethod]
        public void Archive_ValidTicket_SuccessfulArchive()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            Mapper.CreateMap<TicketDTO, Ticket>();

            // Act
            ticketRepo.Archive((ticketRepo.GetAll(false) as List<TicketDTO>)[0]);

            // Assert
            Assert.IsTrue(true);
        }

        [TestMethod]
        public void Archive_NullTicketDTO_ArgumentNullException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            TicketDTO ticket = null;
            var assert = false;

            // Act
            try
            {
                ticketRepo.Archive(ticket);
            }
            catch (ArgumentNullException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void Archive_NonexistingTicket_InvalidOperationException()
        {
            // Arrange
            var ticketRepo = new TicketRepository();
            var ticket = new TicketDTO();
            var assert = false;

            // Act
            try
            {
                ticket.Number = "1990Apr2jsmith19:07"; // Does not exist in database
                ticketRepo.Archive(ticket);
            }
            catch (InvalidOperationException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }
    }
}
